package estructurassa.expertos;

import estructurassa.entidades.ClasificacionProducto;
import estructurassa.entidades.DetalleProductoIntermedio;
import estructurassa.entidades.ProductoIntermedio;
import estructurassa.entidades.ProductoTerminado;
import estructurassa.entidades.RutaFabricacion;
import estructurassa.expertos.excepciones.ABMProductoIntermedioExeption;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import persistencia.Conexion;
import persistencia.Fachada;
import persistencia.exceptions.ExcepcionFachada;

/**
 *
 * @author Juan
 */
public class ExpertoABMProductoIntermedio implements Experto {

    public void guardar(ProductoIntermedio productoIntermedio) throws ABMProductoIntermedioExeption, ExcepcionFachada {
        validarProductoIntermedio(productoIntermedio);
        validarExistencia(productoIntermedio);
        String codigo;
        codigo = ((ExpertoCodigo) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.GENERAR_CODIGO)).generarCodigo(productoIntermedio);
        productoIntermedio.setCodigo(codigo);
        productoIntermedio.setVigente(true);
        try {
            Conexion.getInstancia().iniciarTX();
            Fachada.getInstancia().guardar(productoIntermedio);
            Conexion.getInstancia().confirmarTx();
        } catch (ExcepcionFachada ex) {
            Conexion.getInstancia().deshacerTx();
            throw ex;
        }

    }

    public void darBaja(ProductoIntermedio producto) throws ABMProductoIntermedioExeption, ExcepcionFachada {
        Criteria componenteProducto = Fachada.getInstancia().crearCriterio(RutaFabricacion.class);
        componenteProducto.createCriteria("estapasFabricacion").add(Restrictions.eq("productoIntermedio", producto));
        List rutasFabricacion = Fachada.getInstancia().buscar(RutaFabricacion.class, componenteProducto);
        List productosEncontrados = new ArrayList();
        for (Object object : rutasFabricacion) {
            Criteria productoRutas = Fachada.getInstancia().crearCriterio(ProductoTerminado.class).add(Restrictions.eq("rutaFabricacion", ((RutaFabricacion)object)));
            productosEncontrados.add(Fachada.getInstancia().buscar(ProductoTerminado.class, productoRutas).get(0));
        }
        
        if (!rutasFabricacion.isEmpty()) {
            throw new ABMProductoIntermedioExeption("El producto "+producto.getNombre()+" se encuentra en etapas de fabricación de los siguientes productos: \n" + productosEncontrados);
        }
        
        producto.setVigente(false);
        try {
            Conexion.getInstancia().iniciarTX();
            Fachada.getInstancia().guardar(producto);
            Conexion.getInstancia().confirmarTx();
        } catch (ExcepcionFachada ex) {
            Conexion.getInstancia().deshacerTx();
            throw ex;
        }
    }

    public List buscarProductosIntermedios() {
        Criteria vigente = Fachada.getInstancia().crearCriterio(ProductoIntermedio.class).add(Restrictions.eq("vigente", true));
        return Fachada.getInstancia().buscar(ProductoIntermedio.class, vigente);
    }

    private void validarProductoIntermedio(ProductoIntermedio producto) throws ABMProductoIntermedioExeption {

        if (producto.getNombre().length() == 0) {
            throw new ABMProductoIntermedioExeption("Falta Ingresar Nombre");
        }
    }

    private void validarExistencia(ProductoIntermedio producto) throws ABMProductoIntermedioExeption {
        if (producto.getId() != null) {
            return;
        }
        Criteria nombre = Fachada.getInstancia().crearCriterio(ProductoIntermedio.class);
        nombre.add(Restrictions.eq("nombre", producto.getNombre()).ignoreCase());
        nombre.add(Restrictions.eq("vigente", true));
        if (!Fachada.getInstancia().buscar(ProductoIntermedio.class, nombre).isEmpty()) {
            throw new ABMProductoIntermedioExeption("Producto ya existente");
        }
    }

    public List buscarClasificacionesProductos() {
        Criteria vigente = Fachada.getInstancia().crearCriterio(ClasificacionProducto.class).add(Restrictions.eq("vigente", true));
        vigente.createCriteria("categoriaBrisch").add(Restrictions.eq("codigo", "3"));
        return Fachada.getInstancia().buscar(ClasificacionProducto.class, vigente);
    }
}
